﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using netCoreStudy.Attr;
using netCoreStudy.Attr.QueryAttr;
using netCoreStudy.Entities.Base;
using Newtonsoft.Json;

namespace netCoreStudy
{
	/// <summary>
	/// 自己定义 的公共方法 
	/// </summary>
	public static class MyCommonMethod
	{
		private const string _desc = " desc";


			
		/// <summary>
		/// 获取 entity 中的 list  T name 转换 为 dto 中的 list T 的 T name1
		/// <param name="prop"></param>
		/// <returns></returns>
		/// </summary>
		public static string GetDtoListTName(this PropertyInfo prop)
		{
			IncludeAttribute includeAttribute = prop.GetCustomAttribute<IncludeAttribute>();
			if (includeAttribute == null) return "error";
			// thenInclude 为空则代表 这个是 一级关联  
			if (includeAttribute.FullInclude == null)
			{
				return prop.Name + "Dto";
			}

			// 否则 是 二级 关联 
			return includeAttribute.FullInclude + "Dto";
		}

		/// <summary>
		/// 获取 注释名称 
		/// </summary>
		/// <param name="prop"></param>
		/// <returns></returns>
		public static string GetCommentName(this Type prop)
		{
			CommentAttribute commentAttribute = prop.GetCustomAttribute<CommentAttribute>();
			return commentAttribute == null ? "未写注释" : commentAttribute.Name;
		}

		/// <summary>
		/// 获取 注释名称 
		/// </summary>
		/// <param name="prop"></param>
		/// <returns></returns>
		public static string GetCommentName(this PropertyInfo prop)
		{
			CommentAttribute commentAttribute = prop.GetCustomAttribute<CommentAttribute>();
			return commentAttribute == null ? "未写注释" : commentAttribute.Name;
		}

		/// <summary>
		/// 首字母大写
		/// </summary>
		/// <returns></returns>
		public static string CaseFirstLetter(this string input)
		{
			return input.Substring(0, 1).ToUpper() + input.Substring(1);
		}

		/// <summary>
		/// System 转换下字符串 Web vue 
		/// </summary>
		/// <param name="prop"></param>
		/// <returns></returns>
		public static string PropStrWebConvert(this PropertyInfo prop)
		{
			string returnStr = "''";
			if (prop.PropertyType.Name == "Int32") returnStr = "0";
			if (prop.PropertyType.Name == "Int64") returnStr = "0";
			if (prop.PropertyType.Name == "String") returnStr = "''";
			if (prop.PropertyType.Name == "Boolean") returnStr = "true";
			if (prop.PropertyType.Name.StartsWith("List")) returnStr = "[]";
			return returnStr;
		}

		/// <summary>
		/// 首字母小写
		/// </summary>
		/// <returns></returns>
		public static string LowerCaseFirstLetter(this string input)
		{
			return input.Substring(0, 1).ToLower() + input.Substring(1);
		}

		/// <summary>
		/// 获取程序集名称 
		/// </summary>
		/// <returns></returns>
		public static string GetAssemblyName()
		{
			return Assembly.GetExecutingAssembly().GetName().Name;
		}

		/// <summary>
		/// System 转换下字符串
		/// </summary>
		/// <param name="prop"></param>
		/// <returns></returns>
		public static string SystemStrConvert(this PropertyInfo prop)
		{
			string returnStr = "";
			if (prop.PropertyType.Name == "Int32") returnStr = "int";
			if (prop.PropertyType.Name == "Int64") returnStr = "long";
			if (prop.PropertyType.Name == "String") returnStr = "string";
			if (prop.PropertyType.Name == "Boolean") returnStr = "bool";
			// list 开头的 则 转成 dto 
			if (prop.PropertyType.Name.StartsWith("List")) returnStr = $"List<{prop.GetDtoListTName()}>";

			return returnStr;
		}

		/// <summary>
		/// 项目的类 转换下字符串
		/// </summary>
		/// <param name="prop"></param>
		/// <param name="entityNames">实体文件夹里面 的 实体类列表 </param>
		/// <returns></returns>
		public static string ProjStrConvert(this string prop, IEnumerable<string> entityNames)
		{
			// 如果是实体类的话，给他加上 dto 
			if (entityNames.Any(x => x == prop))
			{
				prop = prop + "Dto";
			}

			return prop;
		}

		/// <summary>
		/// 将object 打印成 json 
		/// </summary>
		/// <param name="obj"></param>
		public static void JsonCW(this object obj)
		{
			string serializeObject = JsonConvert.SerializeObject(obj, Formatting.Indented,
				new JsonSerializerSettings()
					{ReferenceLoopHandling = ReferenceLoopHandling.Ignore});
			Console.WriteLine(serializeObject);
		}

		public static string TimeSubTract(DateTime time1, DateTime time2)
		{
			TimeSpan subTract = time1.Subtract(time2);
			return $"{subTract.Days} 天 {subTract.Hours} 时 {subTract.Minutes} 分 ";
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="thisValue"></param>
		/// <returns></returns>
		public static int ObjToInt(this object thisValue)
		{
			int reval = 0;
			if (thisValue == null) return 0;
			if (thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
			{
				return reval;
			}

			return reval;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="thisValue"></param>
		/// <returns></returns>
		public static string ObjToString(this object thisValue)
		{
			if (thisValue != null) return thisValue.ToString().Trim();
			return "";
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="thisValue"></param>
		/// <returns></returns>
		public static bool IsNotEmptyOrNull(this object thisValue)
		{
			return ObjToString(thisValue) != "" && ObjToString(thisValue) != "undefined" &&
			       ObjToString(thisValue) != "null";
		}

		/// <summary>
		/// string 删除结尾的 " desc"
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static string RemoveDesc(this string input)
		{
			input = input.Trim();
			if (input.EndsWith(_desc))
			{
				input = input.Replace(_desc, "");
			}

			return input;
		}

		/// <summary>
		/// 判断 string 结尾 是否含有 " desc"
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static bool JudgeDesc(this string input)
		{
			return input.EndsWith(_desc);
		}

		/// <summary>
		/// DateTime转时间戳
		/// </summary>
		/// <param name="time">DateTime时间</param>
		/// <param name="type">0为毫秒,1为秒</param>
		/// <returns></returns>
		public static string ConvertTimestamp(DateTime time, int type = 0)
		{
			double intResult = 0;
			DateTime startTime =
				TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
			if (type == 0)
			{
				intResult = (time - startTime).TotalMilliseconds;
			}
			else if (type == 1)
			{
				intResult = (time - startTime).TotalSeconds;
			}
			else
			{
				Console.WriteLine("参数错误!");
			}

			return Math.Round(intResult, 0).ToString();
		}

		/// <summary>
		/// 检测long 类型 不是 0 
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static bool CheckNotZero(this long input)
		{
			return input != 0;
		}

		/// <summary>
		/// 检测int 类型 不是 0 
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static bool CheckNotZero(this int input)
		{
			return input != 0;
		}

		/// <summary>
		/// 时间戳转DateTime
		/// </summary>
		/// <param name="timestamp">时间戳</param>
		/// <returns></returns>
		public static DateTime Ts2DateTime(this long timestamp)
		{
			// DateTimeOffset fromUnixTimeMilliseconds = DateTimeOffset.FromUnixTimeMilliseconds(timestamp);
			string s = timestamp.ToString();
			DateTime time = DateTime.MinValue;
			DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
			if (s.Length == 10) //精确到秒
			{
				time = startTime.AddSeconds(double.Parse(s));
			}
			else if (s.Length == 13) //精确到毫秒
			{
				time = startTime.AddMilliseconds(double.Parse(s));
			}

			return time;
		}

		/// <summary>
		/// datetime 转 时间戳
		/// </summary>
		/// <param name="dateTime"></param>
		/// <returns></returns>
		public static long DateTime2Ts(this DateTime dateTime)
		{
			DateTimeOffset dto = new DateTimeOffset(dateTime);
			long timestamp = dto.ToUnixTimeMilliseconds();
			return timestamp;
		}

		/// <summary>
		/// Unix时间戳转DateTime
		/// </summary>
		/// <param name="timestamp">时间戳</param>
		/// <returns></returns>
		public static DateTime ConvertToDateTime(this string timestamp)
		{
			DateTime time = DateTime.MinValue;
			DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
			if (timestamp.Length == 10) //精确到秒
			{
				time = startTime.AddSeconds(double.Parse(timestamp));
			}
			else if (timestamp.Length == 13) //精确到毫秒
			{
				time = startTime.AddMilliseconds(double.Parse(timestamp));
			}

			return time;
		}

		/// <summary>
		/// 32位MD5加密
		/// </summary>
		/// <param name="password"></param>
		/// <returns></returns>
		public static string Md5Encrypt32(string password = "")
		{
			string pwd = string.Empty;
			MD5 md5 = MD5.Create(); //实例化一个md5对像
			// 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
			byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(password));
			// 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得
			foreach (var item in s)
			{
				// 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字
				// 母，如果使用大写（X）则格式后的字符是大写字符 
				pwd = string.Concat(pwd, item.ToString("X2"));
			}

			return pwd;
		}

		/// <summary>
		/// 根据枚举值获得 枚举名称 
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public static string GetEnumName(this System.Enum input)
		{
			return System.Enum.GetName(input.GetType(), input);
		}

		/// <summary>
		/// 返回成功消息 
		/// </summary>
		/// <param name="controllerBase"></param>
		/// <param name="msg"></param>
		/// <returns></returns>
		public static OkObjectResult SuccessMsg(this ControllerBase controllerBase, string msg)
		{
			return controllerBase.Ok(new ResMsg(true, $"{msg}"));
		}

		/// <summary>
		/// 返回成功消息 
		/// </summary>
		/// <param name="controllerBase"></param>
		/// <param name="msg">成功消息</param>
		/// <param name="body">实体</param>
		/// <returns></returns>
		public static OkObjectResult SuccessMsg<T>(this ControllerBase controllerBase, string msg,
			T body)
		{
			return controllerBase.Ok(new ResMsg<T>(body, true, $"{msg}"));
		}

		/// <summary>
		/// 返回失败消息 
		/// </summary>
		/// <param name="controllerBase"></param>
		/// <param name="msg"></param>
		/// <returns></returns>
		public static OkObjectResult FailMsg(this ControllerBase controllerBase, string msg)
		{
			return controllerBase.Ok(new ResMsg(false, $"{msg}", 400));
		}

		/// <summary>
		/// abp 的 where if 
		/// </summary>
		/// <param name="query"></param>
		/// <param name="condition"></param>
		/// <param name="predicate"></param>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition,
			Expression<Func<T, bool>> predicate)
		{
			return condition ? query.Where(predicate) : query;
		}

		/// <summary>
		/// abp 的 where if 
		/// </summary>
		/// <param name="query"></param>
		/// <param name="condition"></param>
		/// <param name="predicate"></param>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition,
			Expression<Func<T, int, bool>> predicate)
		{
			return condition ? query.Where(predicate) : query;
		}

		/// <summary>
		/// abp 的 where if 
		/// </summary>
		/// <param name="query"></param>
		/// <param name="condition"></param>
		/// <param name="predicate"></param>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> query, bool condition, Func<T, bool> predicate)
		{
			return condition ? query.Where(predicate) : query;
		}

		/// <summary>
		/// where 根据 baseParameter 来查询 列表 
		/// </summary>
		/// <param name="query"></param>
		/// <param name="param"></param>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		public static IQueryable<T> WhereBase<T>(this IQueryable<T> query, BaseParameter param) where T : BaseEntity
		{
			IQueryable<T> queryRes = query.Where(x => x.IsRemoved);
			queryRes.WhereIf(param.StartTime != 0, x => x.CreateTime >= param.StartTime);
			queryRes.WhereIf(param.EndTime != 0, x => x.CreateTime <= param.EndTime);
			return queryRes;
		}
	}
}